﻿using System;
using System.Collections.Generic;
using System.Linq;
using GCTrackableRace.Interfaces;
using GcTrackableRace.Entities;

namespace GcTrackableRace.ScoreCalculator.Rules
{
	public class SpecificProvincesAndStatesVisitedRule : BaseRule, IRaceRule
	{
		public SpecificProvincesAndStatesVisitedRule(string reportColumnName, string startDate, string endDate, string pointAllocation, string keywords, 
			IGeocacheInfo geocacheInfo, ILocationInfoLookup locationInfoLookup)
			: base(reportColumnName, startDate, endDate, pointAllocation)
		{
			Keywords = keywords.Split( new[]{';','|'}, StringSplitOptions.RemoveEmptyEntries).Select(k => k.Trim()).ToList();

			GeocacheInfo = geocacheInfo;

			LocationInfoLookup = locationInfoLookup;
		}

		private ILocationInfoLookup LocationInfoLookup { get; set; }

		private IEnumerable<string> Keywords { get; set; }

		private IGeocacheInfo GeocacheInfo { get; set; }

		protected override void SetRuleName()
		{
			RuleName = "Specific Countries Visited Rule";
		}

		public override void Process(ITrackable trackable, IEnumerable<ITrackableLog> trackableLogs)
		{
			var allValidDroppedAndVisitedLogs = (
				from log in trackableLogs
				let geocache = GeocacheInfo.GetDetail(log.LocationGcCode)
				where (
					(log.LogType == LogType.DroppedOff
					||
					(
						log.LogType == LogType.Visited
						&&
						(geocache != null && geocache.IsEarthCache)
					))
					&&

						(
							log.Date >= StartDate
							&&
							log.Date <= EndDate
						)
					)
				select log)
				.OrderBy(logs => logs.Date)
				.ThenBy(logs => logs.LogId)
				.ToList();

			var validCacheInProvincesAndStatesVisits = (
				from log in allValidDroppedAndVisitedLogs 
				let stateOrProvince = LocationInfoLookup.GetProvinceOrStateUsingCoords(log.Latitude, log.Longitude)
				let found = Keywords.Any(w => w.ToLowerInvariant() == stateOrProvince.ToLowerInvariant()) 
				where found
				select String.Format("{0}({1})", log.LocationGcCode, stateOrProvince)).ToList();

			trackable.AddScore(new RuleScore(
				RuleName, 
				ReportColumnName,
				validCacheInProvincesAndStatesVisits.Count,
				(int)(validCacheInProvincesAndStatesVisits.Count * PointAllocation),
				String.Join("|", validCacheInProvincesAndStatesVisits).Trim('|')));
		}
	}
}
